package com.bestcem.xm.qdes.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bestcem.xm.common.core.annotation.XmGet;
import com.bestcem.xm.common.core.domain.web.XmResultJson;
import com.bestcem.xm.common.core.enums.ReqErrorCodeEnum;
import com.bestcem.xm.common.core.exception.BusinessException;
import com.bestcem.xm.component.security.context.SecurityContextHolder;
import com.bestcem.xm.qdes.controller.vo.QuestionLibProjectDetailVo;
import com.bestcem.xm.qdes.entity.QdesProject;
import com.bestcem.xm.qdes.entity.QdesProjectExtraAttr;
import com.bestcem.xm.qdes.entity.QdesQstruct;
import com.bestcem.xm.qdes.entity.QdesQuestion;
import com.bestcem.xm.qdes.handler.export.ExportContext;
import com.bestcem.xm.qdes.handler.export.ProjectExportHandler;
import com.bestcem.xm.qdes.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Api(tags = "问卷编辑")
@RestController
@RequiredArgsConstructor
@RequestMapping("/qdes/projects")
public class ProjectController {
    private @NonNull QdesQuestionLibService questionlibService;
    private @NonNull QdesProjectExtraAttrService projectextraattrService;
    private @NonNull QdesProjectService projectService;
    private @NonNull QdesQstructService qstructService;
    private @NonNull QdesQuestionService questionService;
    private @NonNull ProjectExportHandler projectExportHandler;

    @ApiOperation(value = "微信投放初始化")
    @GetMapping("/{id:[a-fA-F0-9]{24}}/initwechatqrcode/")
    public XmResultJson<JSONObject> initWechatQrcode(@PathVariable String id) {
        return XmResultJson.success(projectService.initWechatQrcode(id));
    }

    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "path", dataTypeClass = String.class, name = "id", value = "主键")
    })
    @ApiOperation(value = "题目库-添加模板-问卷项目选中后详情查询", notes = "题目库-添加模板-问卷项目选中后详情查询", httpMethod = "GET")
    @GetMapping("/{id:[a-fA-F0-9]{24}}")
    public XmResultJson<QuestionLibProjectDetailVo> projectsDetail(@PathVariable String id) {
        return XmResultJson.success(questionlibService.projectsDetail(id));
    }


    @ApiOperation(value = "获取问卷敏感信息配置")
    @GetMapping("/{projectId:[a-fA-F0-9]{24}}/projectextraattrs")
    public XmResultJson<QdesProjectExtraAttr> projectExtraAttrsGet(@PathVariable String projectId) {
        return XmResultJson.success(projectextraattrService.getByProjectId(projectId));
    }


    @ApiOperation(value = "设置问卷敏感信息配置")
    @PutMapping("/{projectId:[a-fA-F0-9]{24}}/projectextraattrs")
    public XmResultJson<?> projectExtraAttrsPut(@PathVariable String projectId, @RequestBody JSONObject param) {
        return XmResultJson.success(projectextraattrService.putByProjectId(projectId, param));
    }

    @ApiOperation(value = "获取已发布的题目列表")
    @GetMapping("/{pid:[a-fA-F0-9]{24}}/release/questions/")
    public XmResultJson<Object> getReleasedQuestions(@PathVariable String pid) {
        log.info("getReleasedQuestions projectId:{}", pid);
        QdesProject project = projectService.getById(pid);
        if (Objects.isNull(project)) {
            return XmResultJson.fail(-1, String.format("project[id=%s] not found", pid));
        }
        if (Objects.isNull(project.getReleaseVer()) || project.getReleaseVer().equals(0)) {
            return XmResultJson.success(new JSONArray());
        }

        LambdaQueryWrapper<QdesQstruct> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(QdesQstruct::getProjectId, pid)
                .eq(QdesQstruct::getVersion, project.getReleaseVer())
                .last("limit 1");
        QdesQstruct struct = qstructService.getOne(queryWrapper);
        if (Objects.isNull(struct)) {
            return XmResultJson.fail(-1, String.format("qstruct[projectID=%s,version=%d] not found", pid, project.getReleaseVer()));
        }
        return XmResultJson.success(projectService.getReleasedQuestions(project, struct));
    }

    @ApiOperation(value = "获取已发布的题目选项列表")
    @GetMapping("/{pid:[a-fA-F0-9]{24}}/release/options/")
    public XmResultJson<Object> getReleasedOptions(@PathVariable String pid, @RequestParam(value = "gid") Integer gid, @RequestParam(value = "rel", required = false) Boolean rel) {
        log.info("getReleasedOptions projectId:{}", pid);
        QdesProject project = projectService.getById(pid);
        if (Objects.isNull(project)) {
            return XmResultJson.fail(-1, String.format("project[id=%s] not found", pid));
        }
        if (Objects.isNull(project.getReleaseVer()) || project.getReleaseVer().equals(0)) {
            return XmResultJson.success(new JSONArray());
        }

        LambdaQueryWrapper<QdesQstruct> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(QdesQstruct::getProjectId, pid)
                .eq(QdesQstruct::getVersion, project.getReleaseVer())
                .last("limit 1");
        QdesQstruct struct = qstructService.getOne(queryWrapper);
        if (Objects.isNull(struct)) {
            return XmResultJson.fail(-1, String.format("qstruct[projectID=%s,version=%d] not found", pid, project.getReleaseVer()));
        }

        // 获取questions
        LambdaQueryWrapper<QdesQuestion> questionWrapper = Wrappers.lambdaQuery();
        questionWrapper.eq(QdesQuestion::getStructId, struct.getId());
        questionWrapper.eq(QdesQuestion::getGid, gid).last("limit 1");
        QdesQuestion question = questionService.getOne(questionWrapper);
        if (Objects.isNull(question)) {
            return XmResultJson.fail(-1, String.format("question[structID=%s,gid=%d] not found", struct.getId(), gid));
        }

        JSONObject data = JSONObject.parseObject(question.getData());
        if (Objects.isNull(data)) {
            return XmResultJson.success(new JSONArray());
        }
        List<JSONObject> items = JSONArray.parseArray(data.getJSONArray("items").toJSONString(), JSONObject.class);
        List<JSONObject> ret = items.stream().filter(oj -> "O".equals(oj.getString("type"))).collect(Collectors.toList());
        return XmResultJson.success(ret);
    }

    /**
     * {"force":false}
     * {"code": 0, "data": {"link": "survey/project/632c20fe3e2c0c000978b81c/project.js", "draft_id": "632c20fe3e2c0c000978b81d", "version": 3, "releaseVer": 2}}
     */
    @ApiOperation(value = "发布问卷")
    @PostMapping("/{pid:[a-fA-F0-9]{24}}/release/")
    public XmResultJson<Object> releaseProject(@PathVariable String pid, @RequestBody Map<String, Boolean> param) {
        log.info("releaseProject projectId:{}", pid);
        Boolean force = false;
        if (param.containsKey("force")) {
            force = param.get("force");
        }

        QdesProject project = projectService.getById(pid);
        if (Objects.isNull(project)) {
            return XmResultJson.fail(-1, String.format("project[id=%s] not found", pid));
        }

        if (StrUtil.isNotBlank(project.getSource())) {
            //外部项目禁止手动发布
            return XmResultJson.fail(-1, "extend project, update is forbidden");
        }

        //私有化不要配额检查
        //await survey_utils.check_org_rspd_quota(proj)

        QdesQstruct struct = qstructService.getById(project.getStructId());
        if (Objects.isNull(struct)) {
            return XmResultJson.fail(-1, String.format("qstruct[id=%s] not found", project.getStructId()));
        }
        return XmResultJson.success(projectService.releaseProject(project, struct, force));
    }

    @ApiOperation(value = "问卷设置接口")
    @PutMapping(value = {"/{projectId:[a-fA-F0-9]{24}}/attribute/", "/{projectId:[a-fA-F0-9]{24}}/attr/"})
    public XmResultJson<JSONObject> putAttribute(@PathVariable String projectId,
                                                 @Validated @RequestBody JSONObject attrJson) throws IOException {
        return projectService.putAttr(projectId, attrJson);
    }

    @ApiOperation(value = "导出项目")
    @GetMapping("/{projectId:[a-fA-F0-9]{24}}/export")
    public void projectExtraAttrsGet(@PathVariable String projectId,
                                     @XmGet ExportContext context, HttpServletResponse response) {
        context.setProjectId(projectId);
        if ("excel".equals(context.getType())) {
            projectExportHandler.exportToExcel(context, response);
        } else {
            projectExportHandler.exportToWord(context, response);
        }
    }

    @ApiOperation(value = "获取当前项目拥有者")
    @GetMapping("/{projectId:[a-fA-F0-9]{24}}/owner")
    public XmResultJson<JSONObject> projectGetOwner(@PathVariable String projectId) {
        return XmResultJson.success(projectService.getProjectOwner(projectId, SecurityContextHolder.getUserId(),
                SecurityContextHolder.getOrgId()));
    }

    @ApiOperation(value = "打分题数据查询")
    @GetMapping("/{projectId:[a-fA-F0-9]{24}}/score_range/")
    public XmResultJson<JSONObject> queryScoreData(@PathVariable String projectId, @RequestParam Integer gid) {
        Optional.ofNullable(gid).orElseThrow(() -> new BusinessException(String.valueOf(ReqErrorCodeEnum.PARAM_LOST), ":gid is required"));
        return XmResultJson.success(projectService.getScoreRange(projectId, gid));
    }
}
